// 通用工具函数

import dayjs from 'dayjs'
import 'dayjs/locale/zh-cn'
import relativeTimePlugin from 'dayjs/plugin/relativeTime'
import customParseFormatPlugin from 'dayjs/plugin/customParseFormat'

// 配置dayjs
dayjs.locale('zh-cn')
dayjs.extend(relativeTimePlugin)
dayjs.extend(customParseFormatPlugin)

// === 数据类型检查 ===
export const isString = (value: any): value is string => typeof value === 'string'
export const isNumber = (value: any): value is number => typeof value === 'number' && !isNaN(value)
export const isBoolean = (value: any): value is boolean => typeof value === 'boolean'
export const isObject = (value: any): value is object => value !== null && typeof value === 'object' && !Array.isArray(value)
export const isArray = (value: any): value is any[] => Array.isArray(value)
export const isFunction = (value: any): value is Function => typeof value === 'function'
export const isUndefined = (value: any): value is undefined => value === undefined
export const isNull = (value: any): value is null => value === null
export const isEmpty = (value: any): boolean => {
  if (isNull(value) || isUndefined(value)) return true
  if (isString(value) || isArray(value)) return value.length === 0
  if (isObject(value)) return Object.keys(value).length === 0
  return false
}

// === 字符串处理 ===
export const capitalize = (str: string): string => {
  if (!isString(str) || str.length === 0) return str
  return str.charAt(0).toUpperCase() + str.slice(1).toLowerCase()
}

export const camelCase = (str: string): string => {
  return str.replace(/[-_\s]+(.)?/g, (_, char) => char ? char.toUpperCase() : '')
}

export const kebabCase = (str: string): string => {
  return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase()
}

export const snakeCase = (str: string): string => {
  return str.replace(/([a-z])([A-Z])/g, '$1_$2').toLowerCase()
}

export const truncate = (str: string, length: number = 50, suffix: string = '...'): string => {
  if (!isString(str)) return ''
  if (str.length <= length) return str
  return str.slice(0, length) + suffix
}

// 去除HTML标签
export const stripHtml = (html: string): string => {
  return html.replace(/<[^>]*>/g, '')
}

// 高亮关键词
export const highlightKeyword = (text: string, keyword: string): string => {
  if (!keyword) return text
  const regex = new RegExp(`(${keyword})`, 'gi')
  return text.replace(regex, '<mark>$1</mark>')
}

// === 数字处理 ===
export const currency = (amount: number, currency: string = '¥', precision: number = 2): string => {
  if (!isNumber(amount)) return `${currency}0.00`
  return `${currency}${amount.toFixed(precision).replace(/\B(?=(\d{3})+(?!\d))/g, ',')}`
}

export const percentage = (value: number, total: number, precision: number = 1): string => {
  if (!isNumber(value) || !isNumber(total) || total === 0) return '0%'
  return `${((value / total) * 100).toFixed(precision)}%`
}

export const fileSize = (bytes: number, precision: number = 1): string => {
  if (!isNumber(bytes) || bytes === 0) return '0 B'
  
  const units = ['B', 'KB', 'MB', 'GB', 'TB']
  const index = Math.floor(Math.log(bytes) / Math.log(1024))
  const size = bytes / Math.pow(1024, index)
  
  return `${size.toFixed(precision)} ${units[index]}`
}

export const thousandSeparator = (num: number): string => {
  if (!isNumber(num)) return '0'
  return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ',')
}

// === 日期时间处理 ===
export const formatDate = (date: string | Date, format: string = 'YYYY-MM-DD'): string => {
  if (!date) return ''
  return dayjs(date).format(format)
}

export const formatDateTime = (date: string | Date): string => {
  if (!date) return ''
  return dayjs(date).format('YYYY-MM-DD HH:mm:ss')
}

export const formatTime = (date: string | Date): string => {
  if (!date) return ''
  return dayjs(date).format('HH:mm:ss')
}

export const relativeTime = (date: string | Date): string => {
  if (!date) return ''
  return dayjs(date).fromNow()
}

export const isToday = (date: string | Date): boolean => {
  if (!date) return false
  return dayjs(date).isSame(dayjs(), 'day')
}

export const isThisWeek = (date: string | Date): boolean => {
  if (!date) return false
  return dayjs(date).isSame(dayjs(), 'week')
}

export const isThisMonth = (date: string | Date): boolean => {
  if (!date) return false
  return dayjs(date).isSame(dayjs(), 'month')
}

export const getDaysInMonth = (date: string | Date): number => {
  if (!date) return 0
  return dayjs(date).daysInMonth()
}

export const getWeekday = (date: string | Date): string => {
  if (!date) return ''
  const weekdays = ['日', '一', '二', '三', '四', '五', '六']
  return `星期${weekdays[dayjs(date).day()]}`
}

// === 数组处理 ===
export const unique = <T>(array: T[]): T[] => {
  return [...new Set(array)]
}

export const shuffle = <T>(array: T[]): T[] => {
  const result = [...array]
  for (let i = result.length - 1; i > 0; i--) {
    const j = Math.floor(Math.random() * (i + 1));
    [result[i], result[j]] = [result[j], result[i]]
  }
  return result
}

export const chunk = <T>(array: T[], size: number): T[][] => {
  const result: T[][] = []
  for (let i = 0; i < array.length; i += size) {
    result.push(array.slice(i, i + size))
  }
  return result
}

export const groupBy = <T>(array: T[], key: keyof T): Record<string, T[]> => {
  return array.reduce((groups, item) => {
    const groupKey = String(item[key])
    if (!groups[groupKey]) {
      groups[groupKey] = []
    }
    groups[groupKey].push(item)
    return groups
  }, {} as Record<string, T[]>)
}

export const sortBy = <T>(array: T[], key: keyof T, order: 'asc' | 'desc' = 'asc'): T[] => {
  return [...array].sort((a, b) => {
    const aVal = a[key]
    const bVal = b[key]
    
    if (aVal < bVal) return order === 'asc' ? -1 : 1
    if (aVal > bVal) return order === 'asc' ? 1 : -1
    return 0
  })
}

// === 对象处理 ===
export const pick = <T extends object, K extends keyof T>(obj: T, keys: K[]): Pick<T, K> => {
  const result = {} as Pick<T, K>
  keys.forEach(key => {
    if (key in obj) {
      result[key] = obj[key]
    }
  })
  return result
}

export const omit = <T extends object, K extends keyof T>(obj: T, keys: K[]): Omit<T, K> => {
  const result = { ...obj }
  keys.forEach(key => {
    delete result[key]
  })
  return result
}

export const deepClone = <T>(obj: T): T => {
  if (obj === null || typeof obj !== 'object') return obj
  if (obj instanceof Date) return new Date(obj.getTime()) as any
  if (obj instanceof Array) return obj.map(item => deepClone(item)) as any
  if (typeof obj === 'object') {
    const clonedObj = {} as T
    Object.keys(obj).forEach(key => {
      (clonedObj as any)[key] = deepClone((obj as any)[key])
    })
    return clonedObj
  }
  return obj
}

export const merge = <T extends object>(target: T, ...sources: Partial<T>[]): T => {
  return Object.assign({}, target, ...sources)
}

// === URL和查询参数处理 ===
export const parseQuery = (query: string): Record<string, string> => {
  const params = new URLSearchParams(query)
  const result: Record<string, string> = {}
  params.forEach((value, key) => {
    result[key] = value
  })
  return result
}

export const stringifyQuery = (params: Record<string, any>): string => {
  const searchParams = new URLSearchParams()
  Object.entries(params).forEach(([key, value]) => {
    if (value !== null && value !== undefined && value !== '') {
      searchParams.append(key, String(value))
    }
  })
  return searchParams.toString()
}

// === 颜色处理 ===
export const hexToRgb = (hex: string): { r: number; g: number; b: number } | null => {
  const result = /^#?([a-f\d]{2})([a-f\d]{2})([a-f\d]{2})$/i.exec(hex)
  return result ? {
    r: parseInt(result[1], 16),
    g: parseInt(result[2], 16),
    b: parseInt(result[3], 16)
  } : null
}

export const rgbToHex = (r: number, g: number, b: number): string => {
  return `#${[r, g, b].map(x => {
    const hex = x.toString(16)
    return hex.length === 1 ? '0' + hex : hex
  }).join('')}`
}

export const isDarkColor = (color: string): boolean => {
  const rgb = hexToRgb(color)
  if (!rgb) return false
  
  // 使用相对亮度公式
  const brightness = (rgb.r * 299 + rgb.g * 587 + rgb.b * 114) / 1000
  return brightness < 128
}

// === 防抖和节流 ===
export const debounce = <T extends (...args: any[]) => any>(
  func: T,
  wait: number,
  immediate: boolean = false
): ((...args: Parameters<T>) => void) => {
  let timeout: NodeJS.Timeout | null = null
  
  return (...args: Parameters<T>) => {
    const later = () => {
      timeout = null
      if (!immediate) func(...args)
    }
    
    const callNow = immediate && !timeout
    if (timeout) clearTimeout(timeout)
    timeout = setTimeout(later, wait)
    if (callNow) func(...args)
  }
}

export const throttle = <T extends (...args: any[]) => any>(
  func: T,
  wait: number
): ((...args: Parameters<T>) => void) => {
  let timeout: NodeJS.Timeout | null = null
  let lastExecTime: number = 0
  
  return (...args: Parameters<T>) => {
    const now = Date.now()
    
    if (now - lastExecTime > wait) {
      func(...args)
      lastExecTime = now
    } else if (!timeout) {
      timeout = setTimeout(() => {
        func(...args)
        lastExecTime = Date.now()
        timeout = null
      }, wait - (now - lastExecTime))
    }
  }
}

// === 存储相关 ===
export const getStorageSize = (): { localStorage: number; sessionStorage: number } => {
  let localStorageSize = 0
  let sessionStorageSize = 0
  
  // 计算localStorage大小
  for (const key in localStorage) {
    if (localStorage.hasOwnProperty(key)) {
      localStorageSize += localStorage.getItem(key)?.length || 0
    }
  }
  
  // 计算sessionStorage大小
  for (const key in sessionStorage) {
    if (sessionStorage.hasOwnProperty(key)) {
      sessionStorageSize += sessionStorage.getItem(key)?.length || 0
    }
  }
  
  return { localStorage: localStorageSize, sessionStorage: sessionStorageSize }
}

// === 随机工具 ===
export const randomId = (length: number = 8): string => {
  const chars = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'
  let result = ''
  for (let i = 0; i < length; i++) {
    result += chars.charAt(Math.floor(Math.random() * chars.length))
  }
  return result
}

export const randomColor = (): string => {
  return `#${Math.floor(Math.random() * 16777215).toString(16)}`
}

export const randomBetween = (min: number, max: number): number => {
  return Math.floor(Math.random() * (max - min + 1)) + min
}

// === 验证工具 ===
export const isEmail = (email: string): boolean => {
  const regex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/
  return regex.test(email)
}

export const isPhone = (phone: string): boolean => {
  const regex = /^1[3-9]\d{9}$/
  return regex.test(phone)
}

export const isIdCard = (idCard: string): boolean => {
  const regex = /(^\d{15}$)|(^\d{18}$)|(^\d{17}(\d|X|x)$)/
  return regex.test(idCard)
}

export const isUrl = (url: string): boolean => {
  try {
    new URL(url)
    return true
  } catch {
    return false
  }
}

// === 浏览器相关 ===
export const copyToClipboard = async (text: string): Promise<boolean> => {
  try {
    if (navigator.clipboard) {
      await navigator.clipboard.writeText(text)
      return true
    } else {
      // 兼容处理
      const textarea = document.createElement('textarea')
      textarea.value = text
      document.body.appendChild(textarea)
      textarea.select()
      document.execCommand('copy')
      document.body.removeChild(textarea)
      return true
    }
  } catch {
    return false
  }
}

export const downloadFile = (content: string, filename: string, contentType: string = 'text/plain'): void => {
  const blob = new Blob([content], { type: contentType })
  const url = URL.createObjectURL(blob)
  const link = document.createElement('a')
  link.href = url
  link.download = filename
  document.body.appendChild(link)
  link.click()
  document.body.removeChild(link)
  URL.revokeObjectURL(url)
}

export const getQueryParam = (param: string): string | null => {
  const urlParams = new URLSearchParams(window.location.search)
  return urlParams.get(param)
}

export const updateQueryParam = (param: string, value: string): void => {
  const url = new URL(window.location.href)
  url.searchParams.set(param, value)
  window.history.replaceState({}, '', url.toString())
}

// === 性能相关 ===
export const measureTime = async <T>(fn: () => Promise<T>): Promise<{ result: T; time: number }> => {
  const start = performance.now()
  const result = await fn()
  const end = performance.now()
  return { result, time: end - start }
}

export const sleep = (ms: number): Promise<void> => {
  return new Promise(resolve => setTimeout(resolve, ms))
}

// === Apple设计系统相关 ===
export const getAppleStatusColor = (status: string): string => {
  const colorMap: Record<string, string> = {
    success: '#34C759',
    warning: '#FF9500',
    error: '#FF3B30',
    info: '#007AFF',
    pending: '#8E8E93',
    active: '#34C759',
    inactive: '#8E8E93'
  }
  return colorMap[status] || colorMap.info
}

export const getCustomerLevelColor = (level: string): string => {
  const colorMap: Record<string, string> = {
    'VIP客户': '#FF9500',
    '高级客户': '#007AFF',
    '普通客户': '#34C759',
    '潜在客户': '#8E8E93'
  }
  return colorMap[level] || colorMap['普通客户']
}

export default {
  // 类型检查
  isString, isNumber, isBoolean, isObject, isArray, isFunction, isUndefined, isNull, isEmpty,
  
  // 字符串处理
  capitalize, camelCase, kebabCase, snakeCase, truncate, stripHtml, highlightKeyword,
  
  // 数字处理
  currency, percentage, fileSize, thousandSeparator,
  
  // 日期时间
  formatDate, formatDateTime, formatTime, relativeTime, isToday, isThisWeek, isThisMonth,
  getDaysInMonth, getWeekday,
  
  // 数组处理
  unique, shuffle, chunk, groupBy, sortBy,
  
  // 对象处理
  pick, omit, deepClone, merge,
  
  // URL处理
  parseQuery, stringifyQuery,
  
  // 颜色处理
  hexToRgb, rgbToHex, isDarkColor,
  
  // 防抖节流
  debounce, throttle,
  
  // 随机工具
  randomId, randomColor, randomBetween,
  
  // 验证工具
  isEmail, isPhone, isIdCard, isUrl,
  
  // 浏览器相关
  copyToClipboard, downloadFile, getQueryParam, updateQueryParam,
  
  // 性能相关
  measureTime, sleep,
  
  // Apple设计系统
  getAppleStatusColor, getCustomerLevelColor
}